home *** CD-ROM | disk | FTP | other *** search
- page 64,132
- ; ***************************************************************************
- ; AHNUTS.ASM
- ; VERSION 1.0, 6/20/1992
- ; Released to the PUBLIC DOMAIN by the author: Lewis E. Balentine
- ; ***************************************************************************
- ;
- ; --------------- DOS directory functions for MicroSoft PDS -----------------
- ; I am so flustrated with what MS calls "profesional" I could scream !!!!!
- ; Among my list of complaints is the inability to read subdirectory names,
- ; files sizes and dates. This file is a direct result of that flustration.
- ;
- ; I ordered a third party library so I would have those functions. Its
- ; directory functions were very fancy ... not what I wanted. All I
- ; really want is a simple implimentation of DOS findfirst and findnext
- ; functions.
- ;
- ; All else has failed... ... ... Ah Nuts ! ! ! ----------------------------
- ;
- ; WARNING #1: ASSEMBLER code is not my cup of tea. This took me a solid
- ; week of screaming and nashing of teeth as I dug through various manuals
- ; with each line of code. Thus there is very little error handling and none
- ; for DOS critical errors (you will need to use PDS's ON ERROR function).
- ; I chose to use the "KISS" method. Thus no equates, macros, defines or
- ; stack variables (except those passed by PDS) are used. I have tried to
- ; put in enough comments that I could figure out what it was that I did a
- ; week later. Thus someone else should be able to figure it out. (I have
- ; a very short memory refresh).
- ;
- ; WARNING #2: This is written for use with far strings only. I have never
- ; installed the near string library and haven't any idea what will happen
- ; with near strings.
- ;
- ; WARNING #3: What you see is what you get. There is no warranty exspressed,
- ; implied or otherwise.
- ;
- ; REFFERENCES:
- ; The following manuals/books were used in developing this code:
- ; Basic Programer's Guide version 7.0 (c)1989,1988,1887, Microsoft
- ; Macro Assembler 5.0 Programers Guide (c)1987, Microsoft
- ; Macro Assembler 5.1 Update (c)1987, Microsoft
- ; Disk Operating System Ver 3.3 Technical Reference (c)1987,1985, IBM
- ; The 8086 Book (c)1980, Osborne/McGraw-Hill, Russell Rector, George Alexy
- ;
- ; DEBUGGING:
- ; As much as I hate to admit it, this module was debugged using Microsoft
- ; Codeview (because nothing else would work with PDS exe's). I have three
- ; major problems with Codeview:
- ; 1) Although I have PDS 7.1, Quick "C" and Masm 5.1 the only manual I
- ; I have for CV came with MASM 5.0 and it is out of date!
- ; 2) I can not find a way to load the asm source code when debugging
- ; a mixed PDS and ASM executible.
- ; 3) How can anybody get anything done in assembly without a stack window.
- ; A extra memory window is a poor substitute for the real thing.
- ;
- ; LINKING with PDS:
- ; masm ahnuts.asm, ahnuts.obj, ahnuts.lst,;
- ; link /Q ahnuts.obj qbx.lib, ahnuts.qlb, , qbxqlb.lib;
- ; lib ahnuts.lib +ahnuts.obj+qbx.lib;
- ; qbx /l ahnuts.qlb
- ; (at this point you are on your own ..... have fun!)
- ;-----------------------------------------------------------------------------
- .lall ; list all code generated
- extrn STRINGLENGTH:far ; Declare external functions
- extrn STRINGASSIGN:far ; provided by PDS for variable
- extrn STRINGRELEASE:far ; length string operations.
- ;-----------------------------------------------------------------------------
- .model medium,basic ; PDS Prg Guide pg 476.
- .stack
- ;-----------------------------------------------------------------------------
- .data
- olddtao dw 0 ; PDS's Disk Transfer Area offset
- olddtas dw 0 ; PDS's Disk Transfer Area segment
- ourdta db 21 dup (0) ; Our DTA, 21 Bytes for DOS
- ouratr db 0 ; , file atribute
- ourtime dw 0 ; , file time
- ourdate dw 0 ; , file date
- ourlosz dw 0 ; , low word of file size
- ourhisz dw 0 ; , high word of file size
- ourname db 13 dup (0) ; , file name
- db 0 ; ... Just say this is insurance.
- work db 130 dup (0) ; Our string space.
- strdsc dd 0 ; Our return string descriptor.
- found dw 0 ; Used to determine previous call.
- ourerr dw 0 ; Store our exit error code.
-
- .code
- ;-----------------------------------------------------------------------------
- ; FindFile
- ; INPUT:
- ; Function takes 2 parameters, a string and a integer.
- ; The first call should contain a search mask for the file name and a
- ; value for the search atribute.
- ;
- ; The second call should contain a null string for the file mask. The
- ; passed attribute will be ignored on the second call.
- ;
- ; RETURN:
- ; If a matching file is found the function returns a variable length
- ; string with the file name. On error a NULL string is returned.
- ;
- ; BASIC: (PDS 7.1 with far strings enabled)
- ; Declare Function FindFile$(spec$, atribut%)
- ; ... Thus on entry the stack will look like this
- ; spec string 2 bytes (near pointer to descriptor)
- ; atribute 2 bytes (near pointer to 2 byte integer)
- ; return address 4 bytes (far return)
- ;----------------------------------------------------------------------
- FindFile proc uses si di, spec , atrib ; Per PDS prog guide pg. 478,
- ; push bp ; preserve si di ss ds bp and
- ; mov bp,sp ; direction flag.
- ; push si ; We use PDS's DS and SS.
- ; push di ; "proc uses" directive handles
- ; ... the instructions above are from ; the BP SP registers.
- ; ... the Assembler directive "uses" ; Flags are saved below.
-
- pushf ; First let us save the flags.
- mov ourerr,0 ; Clear our error storage.
-
- ; This routine uses calls to DOS FindFirst and FindNext function,
- ; in either case we need to save the existing DTA and replace it
- ; with our own static data area.
- mov ah,2Fh ; DOS function: Get DTA
- int 21h ; Call DOS
- mov olddtao,bx ; Save old dta offset.
- mov olddtas,es ; Save old dta segment.
- mov dx, offset ds:ourdta ; Set DS:DX to our DTA.
- mov ah, 1Ah ; DOS function: Set DTA
- int 21h ; call DOS
-
- ; Now we need to know if this is new request.
- ; First we need our string length. PDS provide's
- ; a function for this purpose.
- mov ax, spec ; ... Per PDS Prog Guide.
- push ax ; Push the string parameter pointer.
- call stringlength ; Call PDS, length returned in AX
- or ax, ax ; If length <> 0 then
- jnz @F ; jump fwd to label @@, otherwise
- jmp findnext ; jump to find next match file.
-
- ; We have allowed 128 bytes for those long network paths.
- @@: cmp ax, 128 ; If spec is not too long then
- jb @F ; jump fwd to label @@, otherwise
- mov ax, -1 ; define our error code and
- jmp exiter ; jump to exit with error.
-
- ; Now we assume we have a valid spec and need to move it to our
- ; work area so we can append a zero byte. First we save the len.
- @@: mov found,0 ; Release our flag.
- mov bx, ax ; Mov length to BX.
- inc bx ; Add 1 to length of string.
- mov work[bx],0 ; Store a zero to terminate string.
- mov ax, spec ; Per PDS Prog Guide pg 495:
- push ds ; Get the string parameter pointer
- push ax ; and push it on the stack
- xor ax,ax ; Place zero in AX and push it
- push ax ; to indicate variable len string.
- push ds ; Push our Data Segment on stack.
- mov ax, offset ds:work ; Get address of our string space
- push ax ; and push it on the stack.
- dec bx ; Sub 1 from length of string.
- push bx ; Push length of string on stack.
- call stringassign ; Call PDS to move string.
-
- ; Now we set up the DOS call to find first.
- ; DOS exspect the address of the spec in DS:DX and the
- ; 8 bit atribute in CX.
- ; With our 16 bit atribute the low byte holds the BIT spec we want
- ; to match.
- mov bx, atrib ; Get the DS offset of atribute.
- mov cx, [bx] ; Get the value of atibute in CX.
- xor ch,ch ; Zero the top half.
- mov dx, offset ds:work ; Address of our file mask.
- mov ax,4E00h ; DOS FIND FIRST function.
- int 21h ; Call DOS
-
- ; Error code (if carry flag set) will be returned in AX.
- jnc exitok ; If no error, format string, exit.
- jmp exiter ; Otherwise return Null String
-
- findnext: ; We come here on a repeat call to the routine.
- mov ax,found ; We first check to see if
- cmp ax,0 ; the first call found a file.
- jnz @F ; Jump over our error handler.
- mov ax,-2 ; Define return error code.
- jmp exiter ; Exit with error.
- @@: mov ax,4F00h ; DOS FIND NEXT function.
- int 21h ; Call DOS
-
- ; Error code (if carry flag set) will be returned in AX.
- jnc exitok ; If no error, format string, exit.
- ; Otherwise return Null String
- exiter: ; Uhhh ... we come here if we have a problem ...
- ; ... And do we ever have a problem. MS neglected to explain how
- ; to return a NULL string to PDS. I am going to take a wild guess
- ; and try returning a string descriptor that has been processd by
- ; stringrelease.
- mov ourerr,ax ; Store AX as our exit error.
- mov ax,offset ds:strdsc ; Push our string descriptor address
- push ax ; on the stack.
- call stringrelease ; Make our string null (I hope).
- jmp exit ; Ok ... Now we can leave.
-
- exitok: ; We jump here if we found what we are looking for
- mov ax,found ; Set our flag. Just for the heck
- inc ax ; of it we shall keep track of
- mov found,ax ; how many files we have found.
-
- ; Our DTA should now contain the information we desire.
- ; We need to find the zero terminator for the file name.
- cld ; Put the gear box in foward.
- push es ; Save ES.
- push ds ; Make sure ES points to our
- pop es ; data segment.
- mov di,offset ds:ourname ; Destination for scan.
- mov cx,8+1+3+1 ; Scan up to 13 chars (include 0).
- xor ax,ax ; Scan for zero byte.
- repne scasb ; Scan it.
- pop es ; Restore ES.
- mov ax,8+1+3 ; Max chars for filename.
- sub ax,cx ; Sub renainder in cx.
- mov cx,ax ; Store length.
-
- ; Tell PDS about our return string.
- push ds ; Push far pointer to our return
- mov ax, offset ds:ourname ; string on the stack.
- push ax
- push cx ; Push length of string on the stack.
- push ds ; Push address of our return string
- mov ax, offset ds:strdsc ; descriptor.
- push ax
- xor ax,ax ; Push a zero to indicate
- push ax ; a variable length string.
- call stringassign ; Call PDS.
-
- exit: ; Now we will restore PDS's DTA.
- push ds ; Save our data segment
- mov ax, olddtas ; Place new data segment in AX.
- mov dx, olddtao ; Place new offset in DX.
- mov ds,ax ; Set the data segment.
- mov ah, 1Ah ; point DOS to our static DTA
- int 21h ; call DOS
- pop ds ; restore our data segment
- ; On return PDS's exspects the string descriptor's address in AX
- mov ax, offset ds:strdsc ;
-
- popf ; Restore PDS's flags.
-
- ret
- FindFile endp
- ;-----------------------------------------------------------------------------
- ;
- ;
- ; OK. Now that we have all the information we want, we need a way to return
- ; it to basic. We will create seperate functions that return the last found
- ; file's date, time, size, attribute and the last error. Just to keep things
- ; simple we will return everything as a integer.
- ; PDS exspects 2 byte integers to be returned in AX.
- ; PDS exspects 4 byte integers to be returned in DX + AX.
- ;
- ;
- ; WARNING: -------------------
- ; There is no error checking!
- ; If you have not recieved a valid file name from FindFile, or
- ; if you have not called FindFile
- ; these functions will happily return invalid data !!!!
- ;-----------------------------------------------------------------------------
- FileError proc ; Lets do the easy ones first
- mov ax, ourerr ; Retrieve our error code.
- ret
- FileError endp
- ;-----------------------------------------------------------------------------
- FileFound proc
- mov ax, found ; Retrieve number of files found.
- ret
- FileFound endp
- ;-----------------------------------------------------------------------------
- FileAtrb proc
- xor ax,ax ; Place a zero in AX
- mov al, ouratr ; Retrieve our atribute.
- ret
- FileAtrb endp
- ;-----------------------------------------------------------------------------
- ; **************************************************************************
- ; * NOTE: Because DOS file size is unsigned and PDS long interger is *
- ; * signed ---> a negative file size is possible. *
- ; * However it would have to be larger than 2 Gigabytes. *
- ; **************************************************************************
- FileSize proc ; This one is almost as simple.
- mov ax, ourlosz ; Retrieve low order word.
- mov dx, ourhisz ; Retrieve high order word.
- ret
- FileSize endp
- ;-----------------------------------------------------------------------------
- FileSec proc
- mov ax, ourtime ; Retrieve file time.
- and ax, 0000000000011111b ; Mask off the seconds.
- rol ax,1 ; DOS stores time in 2 sec increments.
- ret
- FileSec endp
- ;-----------------------------------------------------------------------------
- FileMin proc
- mov ax, ourtime ; Retrieve file time.
- and ax, 0000011111100000b ; Mask off the minutes.
- mov cl, 5 ; We rotate minutes to the right
- ror ax, cl ; 5 bits.
- ret
- FileMin endp
- ;-----------------------------------------------------------------------------
- FileHrs proc
- mov ax, ourtime ; Retrieve file time.
- and ax, 1111100000000000b ; Mask off the hours
- mov cl, 5 ; We rotate hours to the left
- rol ax, cl ; 5 bits.
- ret
- FileHrs endp
- ;-----------------------------------------------------------------------------
- FileDay proc
- mov ax, ourdate ; Retrieve file date
- and ax, 0000000000011111b ; Mask off the day.
- ret
- FileDay endp
- ;-----------------------------------------------------------------------------
- FileMonth proc
- mov ax, ourdate ; Retrieve file date
- and ax, 0000000111100000b ; Mask off the month
- mov cl, 5 ; We rotate the Month to the right
- ror ax,cl ; 5 bits.
- ret
- FileMonth endp
- ;-----------------------------------------------------------------------------
- FileYear proc
- mov ax, ourdate ; Retrieve file date
- and ax, 1111111000000000b ; Mask off the year
- mov cl, 7 ; We rotate the year to the left
- rol ax,cl ; 7 bits.
- add ax,1980 ; Add the base year 1980 to AX.
- ret
- FileYear endp
- ;-----------------------------------------------------------------------------
- END
-